from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.ext.asyncio import AsyncSession
from typing import Optional
import math

from src.database.database import get_async_db
from src.service.user_service import UserService
from src.schemas.user import (
    UserCreate, UserUpdate, UserLogin, UserChangePassword,
    UserInfo, UserListQuery, UserListResponse, UserListItem,
    Token, UserInfoResponse, UserListResponseModel, TokenResponse
)
from src.utils.response import ApiResponse
from src.constants.resultcode import ResultCode
from .base import RouterMeta
from src.utils.logger import get_logger
from src.middlewares.api_key_middleware import get_user_from_request
import config

logger = get_logger("capcut")

router = APIRouter()


def serialize_user(user) -> dict:
    """序列化用户对象，处理datetime字段"""
    from datetime import timezone, timedelta
    
    # 东八区时区
    china_tz = timezone(timedelta(hours=8))
    
    def format_datetime(dt):
        if dt is None:
            return None
        # 如果datetime没有时区信息，假设为UTC并转换为东八区
        if dt.tzinfo is None:
            dt = dt.replace(tzinfo=timezone.utc)
        # 转换为东八区
        china_dt = dt.astimezone(china_tz)
        return china_dt.strftime("%Y-%m-%d %H:%M:%S")
    
    return {
        "id": user.id,
        "username": user.username,
        "nick_name": user.nick_name,
        "phone": user.phone,
        "email": user.email,
        "avatar": user.avatar,
        "sex": user.sex,
        "open_id": user.open_id,
        "union_id": user.union_id,
        "last_login_ip": user.last_login_ip,
        "last_login_time": format_datetime(user.last_login_time),
        "status": user.status,
        "create_time": format_datetime(user.create_time),
        "create_by": user.create_by,
        "update_time": format_datetime(user.update_time),
        "update_by": user.update_by,
        "del_flag": user.del_flag,
        "remark": user.remark
    }


def serialize_user_list_item(user) -> dict:
    """序列化用户列表项，处理datetime字段"""
    from datetime import timezone, timedelta
    
    # 东八区时区
    china_tz = timezone(timedelta(hours=8))
    
    def format_datetime(dt):
        if dt is None:
            return None
        # 如果datetime没有时区信息，假设为UTC并转换为东八区
        if dt.tzinfo is None:
            dt = dt.replace(tzinfo=timezone.utc)
        # 转换为东八区
        china_dt = dt.astimezone(china_tz)
        return china_dt.strftime("%Y-%m-%d %H:%M:%S")
    
    return {
        "id": user.id,
        "username": user.username,
        "nick_name": user.nick_name,
        "phone": user.phone,
        "email": user.email,
        "avatar": user.avatar,
        "sex": user.sex,
        "last_login_time": format_datetime(user.last_login_time),
        "status": user.status,
        "create_time": format_datetime(user.create_time)
    }


def require_auth(request: Request):
    """检查用户认证"""
    if not hasattr(request.state, 'user_id') or not request.state.user_id:
        raise HTTPException(status_code=401, detail="需要认证")
    
    return {
        'user_id': request.state.user_id,
        'username': request.state.username
    }


def get_client_ip(request: Request) -> str:
    """获取客户端IP"""
    forwarded_for = request.headers.get("X-Forwarded-For")
    if forwarded_for:
        return forwarded_for.split(",")[0].strip()
    
    real_ip = request.headers.get("X-Real-IP")
    if real_ip:
        return real_ip
    
    return request.client.host


@router.post("/register", response_model=UserInfoResponse, name="用户注册")
async def register(
    user_data: UserCreate,
    db: AsyncSession = Depends(get_async_db)
):
    """
    用户注册
    """
    try:
        user = await UserService.create_user(db, user_data)
        user_info = serialize_user(user)
        
        return ApiResponse.success(
            data=user_info,
            message="注册成功"
        )
    except ValueError as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message=str(e)
        )
    except Exception as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="注册失败"
        )


@router.post("/login", response_model=TokenResponse, name="用户登录")
async def login(
    user_data: UserLogin,
    request: Request,
    db: AsyncSession = Depends(get_async_db)
):
    """
    用户登录
    """
    try:
        user = await UserService.authenticate_user(db, user_data.username, user_data.password)
        if not user:
            return ApiResponse.error(
                result_code=ResultCode.ERROR,
                message="用户名或密码错误"
            )
        
        # 更新登录信息
        client_ip = get_client_ip(request)
        await UserService.update_login_info(db, user.id, client_ip)
        
        # 生成token
        access_token = UserService.create_access_token(
            data={"user_id": user.id, "username": user.username}
        )
        
        token_data = Token(
            access_token=access_token,
            token_type="bearer",
            expires_in=UserService.ACCESS_TOKEN_EXPIRE_MINUTES * 60  # 转换为秒
        )
        
        return ApiResponse.success(
            data=token_data,
            message="登录成功"
        )
    except Exception as e:
        logger.error(f"登录失败: {e}" ,exc_info=True)
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="登录失败"
        )


@router.get("/profile", response_model=UserInfoResponse, name="获取用户信息")
async def get_profile(
    request: Request,
    db: AsyncSession = Depends(get_async_db)
):
    """
    获取当前用户信息
    """
    try:
        # 检查认证
        auth_info = require_auth(request)
        user_id = auth_info['user_id']
        
        # 从数据库获取用户信息
        user = await UserService.get_user_by_id(db, user_id)
        if not user:
            return ApiResponse.error(
                result_code=ResultCode.ERROR,
                message="用户不存在"
            )
        
        user_info = serialize_user(user)
        return ApiResponse.success(
            data=user_info,
            message="获取成功"
        )
    except HTTPException as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message=e.detail,
            status_code=e.status_code
        )
    except Exception as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="获取用户信息失败"
        )


@router.put("/profile", response_model=UserInfoResponse, name="更新用户信息")
async def update_profile(
    request: Request,
    user_data: UserUpdate,
    db: AsyncSession = Depends(get_async_db)
):
    """
    更新当前用户信息
    """
    try:
        # 检查认证
        auth_info = require_auth(request)
        user_id = auth_info['user_id']
        
        updated_user = await UserService.update_user(
            db, user_id, user_data, user_id
        )
        
        if not updated_user:
            return ApiResponse.error(
                result_code=ResultCode.ERROR,
                message="用户不存在"
            )
        
        user_info = serialize_user(updated_user)
        return ApiResponse.success(
            data=user_info,
            message="更新成功"
        )
    except ValueError as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message=str(e)
        )
    except Exception as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="更新失败"
        )


@router.post("/change_password", name="修改密码")
async def change_password(
    request: Request,
    password_data: UserChangePassword,
    db: AsyncSession = Depends(get_async_db)
):
    """
    修改密码
    """
    try:
        # 检查认证
        auth_info = require_auth(request)
        user_id = auth_info['user_id']
        
        success = await UserService.change_password(
            db, user_id, password_data.old_password, password_data.new_password
        )
        
        if not success:
            return ApiResponse.error(
                result_code=ResultCode.ERROR,
                message="修改密码失败"
            )
        
        return ApiResponse.success(message="密码修改成功")
        
    except ValueError as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message=str(e)
        )
    except Exception as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="修改密码失败"
        )


@router.get("/list", response_model=UserListResponseModel, name="获取用户列表")
async def get_user_list(
    request: Request,
    page: int = 1,
    page_size: int = 10,
    username: Optional[str] = None,
    nick_name: Optional[str] = None,
    email: Optional[str] = None,
    phone: Optional[str] = None,
    status: Optional[int] = None,
    db: AsyncSession = Depends(get_async_db)
):
    """
    获取用户列表（需要管理员权限）
    """
    try:
        query = UserListQuery(
            page=page,
            page_size=page_size,
            username=username,
            nick_name=nick_name,
            email=email,
            phone=phone,
            status=status
        )
        
        users, total = await UserService.get_user_list(db, query)
        
        # 序列化用户列表项
        user_items = [serialize_user_list_item(user) for user in users]
        
        total_pages = math.ceil(total / page_size) if total > 0 else 0
        
        response_data = {
            "items": user_items,
            "total": total,
            "page": page,
            "page_size": page_size,
            "total_pages": total_pages
        }
        
        return ApiResponse.success(
            data=response_data,
            message="获取成功"
        )
    except Exception as e:
        logger.error(f"获取用户列表失败: {e}" ,exc_info=True)
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="获取用户列表失败"
        )


@router.get("/{user_id}", response_model=UserInfoResponse, name="获取指定用户信息")
async def get_user(
    request: Request,
    user_id: int,
    db: AsyncSession = Depends(get_async_db)
):
    """
    获取指定用户信息
    """
    try:
        user = await UserService.get_user_by_id(db, user_id)
        if not user:
            return ApiResponse.error(
                result_code=ResultCode.ERROR,
                message="用户不存在"
            )
        
        user_info = serialize_user(user)
        return ApiResponse.success(
            data=user_info,
            message="获取成功"
        )
    except Exception as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="获取用户信息失败"
        )


@router.put("/{user_id}", response_model=UserInfoResponse, name="更新指定用户信息")
async def update_user(
    request: Request,
    user_id: int,
    user_data: UserUpdate,
    db: AsyncSession = Depends(get_async_db)
):
    """
    更新指定用户信息（管理员功能）
    """
    try:
        auth_info = require_auth(request)
        c_user_id = auth_info['user_id']
        updated_user = await UserService.update_user(
            db, user_id, user_data,c_user_id
        )
        
        if not updated_user:
            return ApiResponse.error(
                result_code=ResultCode.ERROR,
                message="用户不存在"
            )
        
        user_info = serialize_user(updated_user)
        return ApiResponse.success(
            data=user_info,
            message="更新成功"
        )
    except ValueError as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message=str(e)
        )
    except Exception as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="更新失败"
        )


@router.delete("/{user_id}", name="删除用户")
async def delete_user(
    request: Request,
    user_id: int,
    db: AsyncSession = Depends(get_async_db)
):
    """
    删除用户（软删除）
    """
    try:
        auth_info = require_auth(request)
        c_user_id = auth_info['user_id']
        success = await UserService.delete_user(db, user_id, c_user_id)
        
        if not success:
            return ApiResponse.error(
                result_code=ResultCode.ERROR,
                message="用户不存在"
            )
        
        return ApiResponse.success(message="删除成功")
        
    except Exception as e:
        return ApiResponse.error(
            result_code=ResultCode.ERROR,
            message="删除失败"
        )


# 路由元数据配置
meta = RouterMeta(
    router=router,
    prefix="/user",
    tags=["用户管理"]
) 